<!--
 * @Author: 刘凌晨 liulingchen1109@163.com
 * @Date: 2022-09-18 15:52:02
 * @LastEditTime: 2022-09-19 00:12:58
 * @FilePath: \three-name\index.html
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>three.js</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>
    <div id="box">
    </div>
    <script type="module">

            import * as THREE from "./libs/build/three.module.js"

            // dat.GUI 是一个轻量级的图形用户界面库，可以很容易地创建出能够改变代码变量的界面组件。 
            
            import {dat} from "./libs/dat.gui/dat.gui.js"

            // OrbitControls是THREEJS中最常用的一个控制器，可以帮助我们实现以目标为焦点的旋转缩放，
            // 同时平移相机观察场景的操作，看上去是物体在进行变换，实际上所有的变化都是相机的相对位置在发生改变。
            import {OrbitControls} from "./libs/three.js/jsm/controls/OrbitControls.js"

            import {FontLoader} from "./libs/three.js/jsm/loaders/FontLoader.js"
            import {TextGeometry} from "./libs/three.js/jsm/geometries/TextGeometry.js"

            // 创建场景
            var scene = new THREE.Scene();
            // 背景色
            scene.background = new THREE.Color(0x999999);

            // 创建相机
            var camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000);
            camera.position.set(0,200,700);

            // 创建渲染器 WebGLRenderer
            var render = new THREE.WebGLRenderer();
            render.setClearColor(new THREE.Color(0x000000));
            render.setSize(window.innerWidth,window.innerHeight);
            render.shadowMap.enabled = true;
            
            // 显示区域
            document.getElementById("box").appendChild(render.domElement);
        
            // 移动相机 使用鼠标
            var controls = new OrbitControls(camera,render.domElement);
            controls.update();

            // 创建点光源 需要照亮场景 
            const dirLightBeh = new THREE.DirectionalLight(0xffffff,1.25);
            dirLightBeh.position.set(0,100,-90);
            scene.add(dirLightBeh);


            // 创建字体 FontLoader
            // 字体加载器以 JSON 格式加载字体的类。返回一个字体，它是一个表示字体的Shapes数组。
            // 这在内部使用FileLoader来加载文件。
            var textMesh, gFont;
            const loader = new FontLoader();
            loader.load("./libs/three.js/fonts/FZYaoTi_Regular.json",function(font){
                gFont = font;
                const geometry = new TextGeometry("刘凌晨",{
                    font:font,
                    size:80,
                    height:20,
                    curveSegments:4,
                    bevelEnabled:true,
                    bevelThickness:2,
                    bevelSize:1.5,
                    bevelSegments:4
                });
                // 初始材料
                var materials = [
                    new THREE.MeshPhongMaterial({
                        color:0xFFFFFF,
                        specular: 0xffffff,
                        shininess: 30,
                        shading:THREE.FlatShading
                    }),
                    // new THREE.MeshPhongMaterial({color:0xffffff})
                ]

                textMesh = new THREE.Mesh(geometry,materials);
                textMesh.position.set(-270,0,0);
                scene.add(textMesh);

            });


            // 定义一个 JavaScript 对象（这里假设叫做 controls），该对象将保存希望通过 dat.GUI 改变的属性。
            var ctrlObj = {
                size:80,
                height:20,
                curveSegments:4,
                bevelEnabled:true,
                bevelThickness:2,
                bevelSize:1.5,
                bevelSegments:4
            }

            var ctrl = new dat.GUI();
            ctrl.add(ctrlObj,"size",0,100).onChange(function(e){
                createText();
            });

            ctrl.add(ctrlObj,"height",0,100).onChange(function(e){
                createText();
            });

            ctrl.add(ctrlObj,"curveSegments",1,3).step(1).onChange(function(e){
                createText();
            });

            ctrl.add(ctrlObj,"bevelEnabled").onChange(function(e){
                createText();
            });

            ctrl.add(ctrlObj,"bevelThickness",0,100).onChange(function(e){
                createText();
            });

            ctrl.add(ctrlObj,"bevelSize",0,100).onChange(function(e){
                createText();
            });

            ctrl.add(ctrlObj,"bevelSegments",0,100).step(1).onChange(function(e){
                createText();
            });
           
                
            // 执行动画
            function animate(){ 
                controls.update();
                requestAnimationFrame(animate);
                render.render(scene,camera);
            }
            animate();  

            

            // 通过是添加 window 的 resize 事件，根据浏览器窗口的变动更新相机的aspect
            // 以及 渲染器的渲染范围，实现自适应的效果。
            function onWindowResize(){                
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                render.setSize(window.innerWidth,window.innerHeight);
            }
            window.addEventListener('resize',onWindowResize,false);
            
            // 通过dat.GUI 来控制字体的显示样式
            function createText(){
                scene.remove(textMesh);

                const geometry = new TextGeometry("morning",{
                    font:gFont,
                    size:ctrlObj.size,
                    height:ctrlObj.height,
                    curveSegments:ctrlObj.curveSegments,
                    bevelEnabled:ctrlObj.bevelEnabled,
                    bevelThickness:ctrlObj.bevelThickness,
                    bevelSize:ctrlObj.bevelSize,
                    bevelSegments:ctrlObj.bevelSegments
                });

                //  材料  MeshPhongMaterial
                // Phong网格材质(MeshPhongMaterial) 一种用于具有镜面高光的光泽表面的材质。 
                // 该材质使用非物理的Blinn-Phong模型来计算反射率。
                var materials = [
                    new THREE.MeshPhongMaterial({color:0xffffff,flatShading:true}),
                    new THREE.MeshPhongMaterial({color:0xffffff})
                ]

                // 网格 
                // 网格（Mesh） 表示基于以三角形为polygon mesh（多边形网格）的物体的类。
                //  同时也作为其他类的基类，例如SkinnedMesh。
                textMesh = new THREE.Mesh(geometry,materials);
                textMesh.position.set(-270,0,0);
                scene.add(textMesh);
            }
    </script>
</body>
</html>